package ro.dandanciu.webgallery.ui.interceptors;

import java.util.Set;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import org.apache.log4j.Logger;
import org.apache.struts2.ServletActionContext;

import ro.dandanciu.webgallery.domainmodel.Roles;
import ro.dandanciu.webgallery.domainmodel.User;
import ro.dandanciu.webgallery.services.UserServices;
import ro.dandanciu.webgallery.ui.general.Constants;
import ro.dandanciu.webgallery.ui.general.WebGalleryAction;

import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.ValidationAware;
import com.opensymphony.xwork2.interceptor.LoggingInterceptor;

public class AuthentificatedInterceptor extends LoggingInterceptor {
	/**
	 * Logger for this class
	 */
	private static final Logger logger = Logger
			.getLogger(AuthentificatedInterceptor.class);

	/**
	 * 
	 */
	private static final long serialVersionUID = 3876766517972729614L;

	private static final String LOGIN_ATTEMPT = "l0g1n_@t3mpt";

	private static final String USERNAME = "userId";

	private static final String PASSWORD = "password";

	private UserServices userServices;
	
	
	public String intercept(ActionInvocation invocation) throws Exception {
		if (logger.isDebugEnabled()) {
			logger.debug("intercept(ActionInvocation) - start");
		}

		// Get the action context from the invocation so we can access the
	    // HttpServletRequest and HttpSession objects.
	    final ActionContext context = invocation.getInvocationContext ();
	     
	    WebGalleryAction action = (WebGalleryAction) invocation.getAction();
	    HttpServletRequest request = (HttpServletRequest) context.get(ServletActionContext.HTTP_REQUEST);
	    HttpSession session =  request.getSession (true);

	    // Is there a "user" object stored in the user's HttpSession?
	    User user = (User) session.getAttribute (Constants.SESSION_USER_KEY);
	    if (user == null) {
	        // The user has not logged in yet.

	        // Is the user attempting to log in right now?
	        String loginAttempt = request.getParameter (LOGIN_ATTEMPT);
	        if ((loginAttempt != null && !"".equals(loginAttempt))) { // The user is attempting to log in.
	            // Process the user's login attempt.
	            if (processLoginAttempt (request, session) ) {
	                // The login succeeded send them the login-success page.

					if (logger.isDebugEnabled()) {
						logger.debug("intercept(ActionInvocation) - end");
					}
	                return "login-successfull";
	            } else {
	                // The login failed. Set an error if we can on the action.
	                if (action instanceof ValidationAware) {
	                    ((ValidationAware) action).addActionError ("Username or password incorrect.");
	                }
	            }
	        }

	        // Either the login attempt failed or the user hasn't tried to login yet, 
	        // and we need to send the login form.

			if (logger.isDebugEnabled()) {
				logger.debug("intercept(ActionInvocation) - end");
			}
	        return "login";
	    } else {
	    	if (!checkRequiredRoles(user, action)) {
				if (logger.isDebugEnabled()) {
					logger.debug("intercept(ActionInvocation) - end");
				}
	    		return "not-authorized";
	    	} else {
				String returnString = invocation.invoke();
				if (logger.isDebugEnabled()) {
					logger.debug("intercept(ActionInvocation) - end");
				}
	    		return returnString;
	    	}
	    }
	}

	private boolean checkRequiredRoles(User user, WebGalleryAction action) {
		Set<Roles> userRoles = userServices.getUserRoles(user);
		Set<Roles> actionRoles = action.getRequiredRoles();
		
		return userRoles.containsAll(actionRoles);
	}

	private boolean processLoginAttempt(HttpServletRequest request,
			HttpSession session) {
		boolean loginOk = false;
		String userId = request.getParameter(USERNAME);
		String password = request.getParameter(PASSWORD);
		User user = userServices.getUserByUserIdAndPassword(userId, password);
		if (user != null) {
			session.setAttribute(Constants.SESSION_USER_KEY, user);
			loginOk = true;
		}
		
		return loginOk;
	}

	public void setUserServices(UserServices userServices) {
		this.userServices = userServices;
	}

}
